<template>
  <div class="app-container">
    <el-card class="box-card">
      <div slot="header">
        <span>病虫害图像识别</span>
      </div>

      <!-- 主要上传和预览区域 -->
      <div class="upload-preview-container">
        <!-- 左侧上传区域 -->
        <div class="upload-section">
          <el-upload
            class="upload-demo"
            drag
            action="#"
            :auto-upload="false"
            :on-change="handleImageChange"
            :show-file-list="false"
            accept="image/*"
            :before-upload="beforeUpload"
          >
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">将图片拖到此处，或<em>点击上传</em></div>
            <div class="el-upload__tip" slot="tip">只能上传jpg/png文件，且不超过10MB</div>
          </el-upload>
        </div>

        <!-- 右侧预览区域 -->
        <div class="preview-section" v-if="imageUrl">
          <h3>图片预览:</h3>
          <div class="image-preview-wrapper">
            <img :src="imageUrl" class="preview-image" alt="图片预览" @load="onPreviewLoad" @error="handlePreviewError"/>
            <div v-if="previewStatus" class="image-status">
              {{ previewStatus }}
            </div>
          </div>
        </div>
      </div>

      <el-button
        type="primary"
        :loading="loading"
        @click="recognizePest"
        :disabled="!imageFile"
        style="margin-top: 20px;"
      >
        {{ loading ? '识别中...' : '开始识别' }}
      </el-button>

      <div v-if="resultImage" class="result-container">
        <!-- 并列布局容器 -->
        <div class="result-ai-container">
          <!-- 左侧识别结果 -->
          <div class="result-section">
            <h3>识别结果:</h3>
            <img :src="formattedResultImage" class="result-image" @load="onResultLoad" @error="handleResultError"/>

            <div v-if="resultStatus" class="image-status">
              {{ resultStatus }}
            </div>

            <div v-if="predictions && predictions.length > 0" class="prediction-results">
              <h3>识别详情:</h3>
              <el-table :data="predictions" style="width: 100%; margin-top: 10px">
                <el-table-column prop="class" label="病虫害名称" width="180"></el-table-column>
                <el-table-column prop="confidence" label="置信度" width="120">
                  <template slot-scope="{row}">
                    {{ (row.confidence * 100).toFixed(2) }}%
                  </template>
                </el-table-column>
                <el-table-column prop="bbox" label="位置坐标">
                  <template slot-scope="{row}">
                    {{ formatBbox(row.bbox) }}
                  </template>
                </el-table-column>
              </el-table>
            </div>
          </div>

          <!-- 右侧AI助手 -->
          <div class="ai-section">
            <div class="ai-assistant-section">
              <h3>AI病虫害助手</h3>
              <p>基于识别结果，AI助手可以为您提供更多关于该病虫害的详细信息</p>
              <p>请在结果图片中找到病虫害名称，然后输入下方以得到详细的信息：</p>

              <div v-if="mainDisease" class="ai-trigger">
                <el-button
                  type="primary"
                  @click="askAIAboutDisease"
                  :loading="aiLoading"
                  icon="el-icon-chat-dot-round"
                >
                  询问AI关于「{{ mainDisease }}」的详细信息
                </el-button>
              </div>

              <!-- 内嵌AI对话组件 -->
              <div class="embedded-chat">
                <ai-chat-assistant
                  ref="aiAssistant"
                  :initial-message="initialAIMessage"
                  :auto-send="autoSendQuery"
                />
              </div>
            </div>
          </div>
        </div>

        <div class="action-buttons" style="margin-top: 20px;">
          <el-button type="success" @click="saveRecord" :loading="saveLoading">
            {{ saveLoading ? '保存中...' : '保存记录' }}
          </el-button>
          <el-button type="info" @click="downloadImage">
            下载图片
          </el-button>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script>
import { recognizePest } from "@/api/insect/identify";
import { addRecord } from "@/api/insect/record";
import request from "@/utils/request";
// 引入AI对话组件
import AiChatAssistant from "@/components/AiChatAssistant";

export default {
  name: "PestRecognition",
  components: {
    AiChatAssistant,
  },

  data() {
    return {
      imageFile: null,
      imageUrl: "",
      loading: false,
      saveLoading: false,
      resultImage: null,
      resultContentType: "image/jpeg",
      predictions: [],
      previewStatus: "",
      resultStatus: "",
      // 新增：存储文件路径用于后续清理
      tempFilePaths: [],
      // 新增AI相关数据
      mainDisease: "", // 主要病虫害名称
      aiLoading: false, // AI查询加载状态
      initialAIMessage: "", // 初始化AI消息
      autoSendQuery: false, // 是否自动发送查询
      // 新增：存储识别相关信息用于保存
      recognitionData: {
        originalImage: "", // 原始图片
        resultImage: "", // 结果图片
        predictions: [], // 识别结果
        recognitionTime: null // 识别时间
      }
    };
  },

  computed: {
    formattedResultImage() {
      if (!this.resultImage) return '';
      if (typeof this.resultImage !== 'string') return '';

      // 如果已经是Data URL格式，直接返回
      if (this.resultImage.startsWith('data:')) {
        return this.resultImage;
      }

      // 否则添加前缀
      return `data:${this.resultContentType};base64,${this.resultImage}`;
    }
  },

  watch: {
    // 监听predictions变化，提取主要病虫害
    predictions: {
      handler(newVal) {
        if (newVal && newVal.length > 0) {
          // 找到置信度最高的病虫害
          const mainPrediction = newVal.reduce((prev, current) =>
            (prev.confidence > current.confidence) ? prev : current
          );
          this.mainDisease = mainPrediction.class;

          // 设置初始化AI消息
          this.initialAIMessage = `我识别出了植物病害「${this.mainDisease}」，请告诉我关于这种病害的详细信息，包括症状和防治措施。`;
        }
      },
      immediate: true
    }
  },

  methods: {
    beforeUpload(file) {
      const isJPGOrPNG = file.type === 'image/jpeg' || file.type === 'image/png';
      const isLt10M = file.size / 1024 / 1024 < 10;

      if (!isJPGOrPNG) {
        this.$message.error('只能上传JPG/PNG格式的图片!');
        return false;
      }
      if (!isLt10M) {
        this.$message.error('图片大小不能超过10MB!');
        return false;
      }
      return true;
    },

    // 新增方法：将文件转换为Base64
    fileToBase64(file) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = error => reject(error);
      });
    },

    // 新增方法：向AI询问病虫害详情
    askAIAboutDisease() {
      this.aiLoading = true;

      // 触发AI组件发送消息
      this.autoSendQuery = true;

      // 等待一下确保AI组件已更新
      setTimeout(() => {
        this.autoSendQuery = false;
        this.aiLoading = false;
      }, 100);
    },

    async handleImageChange(file) {
      if (!file) {
        this.$message.error("文件选择失败");
        return;
      }

      const fileObj = file.raw || file;

      if (!this.beforeUpload(fileObj)) {
        return;
      }

      this.imageFile = fileObj;

      if (this.imageUrl) {
        URL.revokeObjectURL(this.imageUrl);
      }

      this.imageUrl = URL.createObjectURL(fileObj);
      this.resultImage = null;
      this.predictions = [];
      this.previewStatus = "图片加载中...";

      // 将原始图片转换为Base64存储
      try {
        this.recognitionData.originalImage = await this.fileToBase64(fileObj);
      } catch (error) {
        console.error("转换图片为Base64失败:", error);
      }
    },

    handlePreviewError(e) {
      console.error("预览图片加载失败:", e);
      this.previewStatus = "预览图片加载失败";
      this.$message.error("预览图片加载失败");
    },

    handleResultError(e) {
      console.error("结果图片加载失败:", e);
      this.resultStatus = "结果图片加载失败";
      this.$message.error("识别结果图片加载失败");
    },

    onPreviewLoad() {
      console.log("预览图片加载成功");
      this.previewStatus = "";
    },

    onResultLoad() {
      console.log("结果图片加载成功");
      this.resultStatus = "";
    },

    async recognizePest() {
      if (!this.imageFile) {
        this.$message.warning("请先选择图片");
        return;
      }

      this.loading = true;
      this.resultStatus = "识别中...";
      const formData = new FormData();
      formData.append("imageFile", this.imageFile);

      try {
        const response = await request({
          method: 'post',
          url: 'http://localhost:5000/predict',
          data: formData,
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        });

        console.log("识别响应:", response);

        if (response && typeof response === 'object') {
          if (response.success) {
            if (response.image) {
              console.log("获取到图片数据，长度:", response.image.length);

              this.resultImage = response.image;
              this.resultContentType = response.contentType || "image/jpeg";

              if (response.predictions) {
                this.predictions = response.predictions;
              }

              // 更新识别数据
              this.recognitionData.resultImage = response.image;
              this.recognitionData.predictions = this.predictions;
              this.recognitionData.recognitionTime = new Date();

              this.$message.success("识别成功");
              this.resultStatus = "识别成功";
            } else {
              console.error("未获取到图片数据:", response);
              this.$message.error("识别失败: 未获取到图片数据");
              this.resultStatus = "识别失败: 未获取到图片数据";
            }
          } else {
            const errorMsg = response.error || "未知错误";
            console.error("识别失败:", errorMsg);
            this.$message.error("识别失败: " + errorMsg);
            this.resultStatus = "识别失败: " + errorMsg;
          }
        } else {
          console.error("响应数据格式不正确:", response);
          this.$message.error("识别失败: 响应数据格式不正确");
          this.resultStatus = "识别失败: 响应数据格式不正确";
        }
      } catch (error) {
        console.error("识别请求失败:", error);

        let errorMessage = "识别失败: ";
        if (error.response && error.response.data && error.response.data.error) {
          errorMessage += error.response.data.error;
        } else if (error.message) {
          errorMessage += error.message;
        } else {
          errorMessage += "未知错误";
        }

        this.$message.error(errorMessage);
        this.resultStatus = errorMessage;
      } finally {
        this.loading = false;
      }
    },

    formatBbox(bbox) {
      if (!bbox) return "";
      if (Array.isArray(bbox)) {
        return `[${bbox.join(", ")}]`;
      }
      return bbox;
    },

    // 修复：添加downloadImage方法
    downloadImage() {
      if (!this.resultImage) {
        this.$message.warning("没有可下载的图片");
        return;
      }

      try {
        let pureBase64 = this.resultImage;
        if (this.resultImage.includes('base64,')) {
          pureBase64 = this.resultImage.split('base64,')[1];
        }

        // 清理Base64数据
        pureBase64 = pureBase64.replace(/[^A-Za-z0-9+/=]/g, '');

        const byteCharacters = atob(pureBase64);
        const byteArrays = [];

        for (let offset = 0; offset < byteCharacters.length; offset += 1024) {
          const slice = byteCharacters.slice(offset, offset + 1024);

          const byteNumbers = new Array(slice.length);
          for (let i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
          }

          const byteArray = new Uint8Array(byteNumbers);
          byteArrays.push(byteArray);
        }

        const blob = new Blob(byteArrays, { type: this.resultContentType });
        const url = URL.createObjectURL(blob);

        const link = document.createElement('a');
        link.href = url;
        link.download = `pest_recognition_${new Date().getTime()}.${this.resultContentType.split('/')[1] || 'jpg'}`;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);

        setTimeout(() => URL.revokeObjectURL(url), 100);

        this.$message.success("图片下载成功");
      } catch (error) {
        console.error("下载失败:", error);
        this.$message.error("图片下载失败");
      }
    },

    async saveRecord() {
      if (!this.resultImage) {
        this.$message.warning("没有可保存的识别结果");
        return;
      }

      this.saveLoading = true;

      try {
        // 准备Base64数据
        let resultImageBase64 = this.recognitionData.resultImage;
        let originalImageBase64 = this.recognitionData.originalImage;

        // 确保是纯Base64格式（去除data URL前缀）
        if (resultImageBase64 && resultImageBase64.includes('base64,')) {
          resultImageBase64 = resultImageBase64.split('base64,')[1];
        }

        if (originalImageBase64 && originalImageBase64.includes('base64,')) {
          originalImageBase64 = originalImageBase64.split('base64,')[1];
        }

        console.log('保存的结果图片Base64长度:', resultImageBase64 ? resultImageBase64.length : 0);
        console.log('保存的原始图片Base64长度:', originalImageBase64 ? originalImageBase64.length : 0);

        // 修复：格式化日期为后端期望的格式
        let recognitionTime = this.recognitionData.recognitionTime;
        if (recognitionTime instanceof Date) {
          // 格式化为 yyyy-MM-dd HH:mm:ss
          const year = recognitionTime.getFullYear();
          const month = String(recognitionTime.getMonth() + 1).padStart(2, '0');
          const day = String(recognitionTime.getDate()).padStart(2, '0');
          const hours = String(recognitionTime.getHours()).padStart(2, '0');
          const minutes = String(recognitionTime.getMinutes()).padStart(2, '0');
          const seconds = String(recognitionTime.getSeconds()).padStart(2, '0');
          recognitionTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
        }

        // 准备保存的数据
        const recordData = {
          resultImage: resultImageBase64,
          originalImage: originalImageBase64,
          predictions: JSON.stringify(this.recognitionData.predictions),
          mainDisease: this.mainDisease,
          confidence: this.predictions.length > 0 ?
            Math.max(...this.predictions.map(p => p.confidence)) : 0,
          recognitionTime: recognitionTime, // 使用格式化后的日期
          imageName: this.imageFile ? this.imageFile.name : '识别图片'
        };

        console.log('保存的数据:', {
          ...recordData,
          resultImage: recordData.resultImage ? recordData.resultImage.substring(0, 100) + '...' : null,
          originalImage: recordData.originalImage ? recordData.originalImage.substring(0, 100) + '...' : null
        });

        // 调用历史记录的添加接口
        const response = await addRecord(recordData);

        if (response.code === 200) {
          this.$message.success("保存成功");
        } else {
          this.$message.error("保存失败: " + response.msg);
        }
      } catch (error) {
        console.error("保存记录失败:", error);
        this.$message.error("保存失败: " + (error.message || '未知错误'));
      } finally {
        this.saveLoading = false;
      }
    }
  },

  beforeDestroy() {
    // 清理临时URL
    if (this.imageUrl) {
      URL.revokeObjectURL(this.imageUrl);
    }
  }
};
</script>

<style scoped>
/* 保持原有的样式不变 */
.app-container {
  padding: 20px;
}

.box-card {
  max-width: 1200px;
  margin: 0 auto;
}

.upload-preview-container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-bottom: 20px;
}

.upload-section, .preview-section {
  flex: 1;
  min-width: 300px;
}

.upload-section {
  display: flex;
  justify-content: center;
}

.preview-section {
  display: flex;
  flex-direction: column;
}

.upload-demo {
  text-align: center;
  margin-bottom: 20px;
}

.image-preview-wrapper {
  flex: 1;
  display: flex;
  flex-direction: column;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  padding: 10px;
  background-color: #fafafa;
}

.preview-image {
  max-width: 100%;
  max-height: 300px;
  margin: 0 auto;
  display: block;
}

/* 识别结果和AI助手并列布局 */
.result-ai-container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-top: 20px;
}

.result-section, .ai-section {
  flex: 1;
  min-width: 300px;
}

.result-section {
  border-right: 1px solid #e6e6e6;
  padding-right: 20px;
}

.result-image {
  max-width: 80%;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 5px;
  margin-bottom: 20px;
}

.prediction-results {
  margin-top: 20px;
}

.ai-assistant-section {
  background-color: #f9f9f9;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #e6e6e6;
}

.ai-assistant-section h3 {
  color: #409EFF;
  margin-top: 0;
}

.ai-trigger {
  margin: 15px 0;
  text-align: center;
}

.embedded-chat {
  margin-top: 15px;
}

.image-status {
  text-align: center;
  color: #909399;
  font-size: 14px;
  margin: 10px 0;
}

.action-buttons {
  text-align: center;
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #e6e6e6;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .upload-preview-container {
    flex-direction: column;
  }

  .upload-section, .preview-section {
    width: 100%;
  }

  .result-section {
    border-right: none;
    border-bottom: 1px solid #e6e6e6;
    padding-right: 0;
    padding-bottom: 20px;
    margin-bottom: 20px;
  }
}
</style>
